package net.sunzc.yunlian.interact.device;

import com.android.ddmlib.*;
import net.sunzc.yunlian.controller.entity.Point;
import net.sunzc.yunlian.interact.device.command.ActionCommand;
import net.sunzc.yunlian.interact.device.command.Command;
import net.sunzc.yunlian.interact.device.command.CommonCommand;
import net.sunzc.yunlian.interact.device.factory.AdbInputCommandFactory;
import net.sunzc.yunlian.interact.device.mini.Frame2Screen;
import net.sunzc.yunlian.interact.device.mini.Gesture;
import net.sunzc.yunlian.interact.device.mini.Mouse2Touch;
import net.sunzc.yunlian.interact.device.mini.Projector;
import net.sunzc.yunlian.utils.Utils;
import net.sunzc.yunlian.view.AndroidScreen;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class AndroidDevice implements CommandInteract {
    private static final String TAG = "AndroidDevice";
    /**
     * 屏幕窗口默认宽度
     */
    private static final int mScaleWidth = 240;
    private Gesture gesture;
    private IDevice device;
    private Projector projector;
    private String size;
    private String abi;
    private String sdk;
    private double mScaleRate;
    private String frameSize;

    public AndroidDevice(IDevice device) {
        this.device = device;
        start();
    }

    private void start() {
        String wmSizeStr;
        try {
            wmSizeStr = shellExecute(CommonCommand.getCommand("wm size"));
        } catch (TimeoutException | AdbCommandRejectedException | ShellCommandUnresponsiveException | IOException e) {
            e.printStackTrace();
            Log.e(TAG, "查询屏幕尺寸失败:" + e.getMessage());
            wmSizeStr = "Physical size: 720x1280";
        }
        size = wmSizeStr.split("size:")[1].trim();
        String sizes[] = size.split("x");
        frameSize = calutateScale(Double.parseDouble(sizes[0]), Double.parseDouble(sizes[1]));
        Log.i(TAG, size + "-->" + frameSize);
        abi = device.getProperty("ro.product.cpu.abi");
        sdk = device.getProperty("ro.build.version.sdk");
        Log.i(TAG, "屏幕尺寸:" + size + "--abi:" + abi + "--sdk:" + sdk);
        gesture = new Mouse2Touch(this);
        projector = new Frame2Screen(this);
        Utils.threadPool.submit(new InstallRunnable());
    }

    @Override
    public String getFrameSize() {
        return frameSize;
    }

    private String calutateScale(double screenWidth, double screenHeight) {
        mScaleRate = screenWidth > mScaleWidth ? screenWidth / (double) mScaleWidth : 1d;
        long scaleHeight = Math.round(screenHeight / mScaleRate);
        return mScaleWidth + "x" + scaleHeight;
    }

    @Override
    public String toString() {
        return getSerialNum();
    }

    @Override
    public String shellExecute(Command command) throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException, IOException {
        Log.i(TAG, command.getFormatedCommand() + " - start");
        CollectingOutputReceiver receiver = new CollectingOutputReceiver();
        if (device.isOnline())
            device.executeShellCommand(command.getFormatedCommand(), receiver, command.getTimeOut(), TimeUnit.MINUTES);
        Log.i(TAG, command.getFormatedCommand() + " - end,命令输出" + receiver.getOutput());
        return receiver.getOutput();
    }

    public void openClient() {
        try {
            shellExecute(AdbInputCommandFactory.getActionCommand(ActionCommand.Action.OPEN_CLIENT));
        } catch (TimeoutException | AdbCommandRejectedException | ShellCommandUnresponsiveException | IOException e) {
            e.printStackTrace();
            Log.e(TAG, "客户端打开失败" + e.getMessage());
        }
    }

    @Override
    public IDevice getDevice() {
        return device;
    }

    @Override
    public void pullFile(String remote, String local) {
        try {
            device.pullFile(remote, local);
        } catch (IOException | AdbCommandRejectedException | TimeoutException | SyncException e) {
            e.printStackTrace();
            Log.e(TAG, "从设备:" + toString() + "中获取文件失败" + remote + "--->" + local + "----错误信息:" + e.getMessage());
        }
    }

    @Override
    public void pushFile(String local, String remote) {
        try {
            device.pushFile(local, remote);
        } catch (IOException | AdbCommandRejectedException | TimeoutException | SyncException e) {
            e.printStackTrace();
            Log.e(TAG, "从设备:" + toString() + "推送文件失败" + local + "--->" + remote + "----错误信息:" + e.getMessage());
        }
    }

    @Override
    public void createForward(int localPort, String remoteSocketName,
                              IDevice.DeviceUnixSocketNamespace namespace) {
        try {
            device.createForward(localPort, remoteSocketName, namespace);
        } catch (TimeoutException | AdbCommandRejectedException | IOException e) {
            e.printStackTrace();
            Log.e(TAG, localPort + "---->" + remoteSocketName + "端口转发失败:" + e.getMessage());
        }
    }

    @Override
    public String getAbi() {
        return abi;
    }

    @Override
    public String getSdk() {
        return sdk;
    }

    @Override
    public String getSerialNum() {
        return device.getSerialNumber();
    }

    @Override
    public String getSize() {
        return size;
    }

    public void setProjectScreen(AndroidScreen listener) {
        projector.setProjectScreen(listener);
    }

    public void takeScreenShot(String absolutePath) {
        projector.takeScreenCapture(absolutePath);
    }

    public void onTouch(Point point) {
        gesture.onTouch(point);
    }

    public void onDown(Point point) {
        gesture.onDown(point);
    }

    public void onRelease() {
        gesture.onRelease();
    }

    public void stop() {
        gesture.stopGesture();
        projector.stopScreenProjector();
    }

    public void restart() {
        gesture.restartGesture();
        projector.restartScreenProjector();
    }

    public double getScaleRate() {
        return mScaleRate;
    }

    private class InstallRunnable implements Runnable {
        private boolean isForceInstall;
        private File mClientApk;

        public InstallRunnable() {
            mClientApk = new File(System.getProperty("user.dir"), "app-debug.apk");
            if (mClientApk.exists()) {//如果是debug则每次都重装手机端
                isForceInstall = true;
            } else {
                mClientApk = new File(System.getProperty("user.dir"), "app-release.apk");
                isForceInstall = false;
            }
        }

        @Override
        public void run() {
            String result = null;
            try {
                CommonCommand command = CommonCommand.getCommand("pm list packages -3 net.sunzc.yunlian");
                result = shellExecute(command);
            } catch (TimeoutException | AdbCommandRejectedException | ShellCommandUnresponsiveException | IOException e) {
                Log.i(TAG, "查询客户端失败");

            }
            Log.i(TAG, "查询结果" + result);
            if (!isForceInstall && !Utils.isEmpty(result) && result.contains("net.sunzc.yunlian")) {
                Log.i(TAG, getSerialNum() + "手机端已经安装");
            } else {
                try {
                    if (device.isOnline()) {
                        Log.i(TAG, "开始安装apk" + mClientApk.getAbsolutePath());
                        device.installPackage(mClientApk.getAbsolutePath(), isForceInstall);
                    }
                    Log.i(TAG, getSerialNum() + "手机端安装完成");
                } catch (InstallException e) {
                    e.printStackTrace();
                    Log.e(TAG, getSerialNum() + "手机端安装失败:" + e.getMessage());
                }
            }
            openClient();
        }
    }
}
